package org.springblade.modules.material.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import javax.validation.Valid;

import org.springblade.common.annotation.ServiceLog;
import org.springblade.common.constant.TrainingOperateConstant;
import org.springblade.common.enums.library.QuestionType;
import org.springblade.common.exception.TrainingServiceException;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.*;
import org.springblade.modules.library.bo.AutoExtractParamBO;
import org.springblade.modules.log.service.IIntegralLogService;
import org.springblade.modules.log.vo.IntegralLogVO;
import org.springblade.modules.material.entity.*;
import org.springblade.modules.material.excel.PaperReleaseExcel;
import org.springblade.modules.material.service.*;
import org.springblade.modules.material.vo.PaperAnswerVO;
import org.springblade.modules.material.vo.PaperReleaseVO;
import org.springblade.modules.material.wrapper.PaperReleaseWrapper;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.tool.constant.BladeConstant;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import static org.springblade.modules.material.service.impl.PaperReleaseDetailServiceImpl.setQuestionScore;

/**
 * 试卷发布表 控制器
 *
 * @author junxin
 * @since 2023-04-07
 */
@RestController
@AllArgsConstructor
@RequestMapping("blade-paperRelease/paperRelease")
@Api(value = "试卷发布表", tags = "试卷发布表接口")
public class PaperReleaseController extends BladeController {

	private final IPaperReleaseService paperReleaseService;
	private final IPaperReleaseDetailService paperReleaseDetailService;
	private final IPaperDetailService paperDetailService;
	private final IPaperService paperService;
	private final IAnswerService answerService;
	private final IReleaseExamUserService releaseExamUserService;
	private final IPaperReleaseRuleService paperReleaseRuleService;
	private final IIntegralLogService integralLogService;

	/**
	 * 试卷发布表 详情
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入paperRelease")
	public R<PaperReleaseVO> detail(PaperReleaseEntity paperRelease) {
		PaperReleaseEntity detail = paperReleaseService.getOne(Condition.getQueryWrapper(paperRelease));
		PaperReleaseVO paperReleaseVO = PaperReleaseWrapper.build().entityVO(detail);
		if (null!=paperReleaseVO.getIsRule()&& 1==paperReleaseVO.getIsRule()){
			List<PaperReleaseRuleEntity> ruleList = paperReleaseRuleService.list(Wrappers.<PaperReleaseRuleEntity>query().lambda().eq(PaperReleaseRuleEntity::getReleaseId, paperReleaseVO.getId()));
			if (CollectionUtil.isNotEmpty(ruleList)) {
				//返回规则
				paperReleaseVO.setRuleList(ruleList.stream().map(rule->{
					AutoExtractParamBO bo=new AutoExtractParamBO();
					BeanUtil.copyProperties(rule,bo);
					return bo;
				}).collect(Collectors.toList()));
			}
		}
		return R.data(paperReleaseVO);
	}


	/**
	 * 试卷发布表 自定义分页
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入paperRelease")
	public R<IPage<PaperReleaseVO>> page(PaperReleaseVO paperRelease, Query query) {
		IPage<PaperReleaseVO> pages = paperReleaseService.selectPaperReleasePage(Condition.getPage(query), paperRelease);
		Date now = new Date();
		pages.getRecords().forEach(item -> {
			if (item.getStartTime().after(now)) {//开始时间在当前时间之后 表示未开始
				item.setExamStatus("未开始");
			} else if (item.getStartTime().before(now) && item.getEndTime().after(now)) {//开始时间在当前时间之前 且当前时间在结束时间之前 表示进行中
				item.setExamStatus("进行中");
			} else {
				item.setExamStatus("已结束");
			}

			if (null!=item.getIsRule()&& 1==item.getIsRule()){
				List<PaperReleaseRuleEntity> ruleList = paperReleaseRuleService.list(Wrappers.<PaperReleaseRuleEntity>query().lambda().eq(PaperReleaseRuleEntity::getReleaseId, item.getId()));
				if (CollectionUtil.isNotEmpty(ruleList)) {
					//返回规则
					item.setRuleList(ruleList.stream().map(rule->{
						AutoExtractParamBO bo=new AutoExtractParamBO();
						BeanUtil.copyProperties(rule,bo);
						return bo;
					}).collect(Collectors.toList()));
				}


			}

		});
		return R.data(pages);
	}

	/**
	 * 试卷发布表 修改
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/update")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "修改", notes = "传入paperRelease")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	@ServiceLog(value = TrainingOperateConstant.RELEASE,operate = TrainingOperateConstant.UPDATE,describe = "修改")
	public R update(@Valid @RequestBody PaperReleaseVO paperRelease) {

		if (null==paperRelease.getIsRule()|| 0==paperRelease.getIsRule()){
			List<PaperReleaseDetailEntity> releaseDetailList = paperReleaseDetailService.queryByReleaseId(paperRelease.getId().toString());
			releaseDetailList.forEach(releaseDetailItem -> {
				setQuestionScore(releaseDetailItem.getQuestionType(), paperRelease, releaseDetailItem);
			});
			paperReleaseDetailService.updateBatchById(releaseDetailList);

			//判断修改时 是否有改动需要特定场所考试
			PaperReleaseEntity oldData = paperReleaseService.getById(paperRelease.getId());
			if (paperRelease.getPermit().intValue()!=oldData.getPermit().intValue()){
				List<ReleaseExamUserEntity> userList=releaseExamUserService.list(Wrappers.<ReleaseExamUserEntity>query()
					.lambda().eq(ReleaseExamUserEntity::getReleaseId,paperRelease.getId()));
				if (CollectionUtil.isNotEmpty(userList)){
					if (1==paperRelease.getPermit())userList.forEach(user-> user.setPermit(0)); //需要特定场所 ，则所有学员考试授权为待授权
					if (0==paperRelease.getPermit()) userList.forEach(user-> user.setPermit(1));//不需要特定场所 ，则所有学员考试授权为已授权
				}
				releaseExamUserService.updateBatchById(userList);

			}
		}else {//表示规则组卷

			List<AutoExtractParamBO> ruleList = paperRelease.getRuleList();
			if (CollectionUtil.isEmpty(ruleList)) throw new TrainingServiceException("至少新增一条组卷规则");

			//删除原先所有规则
			paperReleaseRuleService.remove(Wrappers.<PaperReleaseRuleEntity>query().lambda().eq(PaperReleaseRuleEntity::getReleaseId,paperRelease.getId()));


			//试卷规则处理
			List<PaperReleaseRuleEntity> ruleEntityList = ruleList.stream().map(rule -> {
				PaperReleaseRuleEntity releaseRuleEntity = new PaperReleaseRuleEntity();
				BeanUtil.copy(rule, releaseRuleEntity);
				releaseRuleEntity.setReleaseId(paperRelease.getId());
				return releaseRuleEntity;
			}).collect(Collectors.toList());
			paperReleaseRuleService.saveBatch(ruleEntityList);
		}


		return R.status(paperReleaseService.updateById(paperRelease));
	}


	/**
	 * 试卷发布表 删除
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/remove")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	@ServiceLog(value = TrainingOperateConstant.RELEASE,operate = TrainingOperateConstant.DELETE,describe = "删除")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(paperReleaseService.deleteLogic(Func.toLongList(ids)));
	}


	/**
	 * 导出数据
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/export-paperRelease")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "导出数据", notes = "传入paperRelease")
	public void exportPaperRelease(@ApiIgnore @RequestParam Map<String, Object> paperRelease, BladeUser bladeUser, HttpServletResponse response) {
		QueryWrapper<PaperReleaseEntity> queryWrapper = Condition.getQueryWrapper(paperRelease, PaperReleaseEntity.class);
		//if (!AuthUtil.isAdministrator()) {
		//	queryWrapper.lambda().eq(PaperRelease::getTenantId, bladeUser.getTenantId());
		//}
		queryWrapper.lambda().eq(PaperReleaseEntity::getIsDeleted, BladeConstant.DB_NOT_DELETED);
		List<PaperReleaseExcel> list = paperReleaseService.exportPaperRelease(queryWrapper);
		ExcelUtil.export(response, "试卷发布表数据" + DateUtil.time(), "试卷发布表数据表", list, PaperReleaseExcel.class);
	}

	/**
	 * 发布考试
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/release-exam")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "发布考试", notes = "传入paperRelease")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	@ServiceLog(value = TrainingOperateConstant.RELEASE,operate = TrainingOperateConstant.ADD,describe = "发布考试")
	public R releaseExam(@Valid @RequestBody PaperReleaseVO vo) {
		if (ObjectUtil.isEmpty(vo.getIsRule())) throw new TrainingServiceException("请选择是否规则组题");
		//非规则组题 isRule=0
		if (0==vo.getIsRule()){
			//1.试卷发布保存
			Long paperId = vo.getPaperId();
			PaperEntity paperEntity = paperService.getById(paperId);
			if (null == paperEntity) throw new TrainingServiceException("该试卷已丢失");
			vo.setIsNeedReview(paperEntity.getIsNeedReview());//设置试卷是否需要批阅

			if (vo.getPassingScore()>vo.getTotalScore()) throw new TrainingServiceException("合格成绩不能大于试卷总分!");

			//课程测试不能有简答题
			if (vo.getExamineType() == 1) {
				if (paperEntity.getIsNeedReview() == 1) {
					throw new TrainingServiceException("课程测试的试卷不能有简答题");
				}
				//不可重复设置课程测试
				PaperReleaseEntity paperReleaseEntity = paperReleaseService.getOne(Wrappers.<PaperReleaseEntity>query().lambda()
					.eq(PaperReleaseEntity::getCourseId, vo.getCourseId())
					.eq(PaperReleaseEntity::getExamineType, 1));
				if (null != paperReleaseEntity) throw new TrainingServiceException("该课程已设置了课程测试");
			}
			if (null==vo.getPeriod() || vo.getPeriod()<0 ) vo.setPeriod(0);
			if (null==vo.getIntegral() || vo.getIntegral()<0) vo.setIntegral((float)0);
			paperReleaseService.save(vo);
			//2.获取试卷详情表数据
			List<PaperDetailEntity> paperDetailList = paperDetailService.queryByPaperId(paperId);
			if (CollectionUtil.isEmpty(paperDetailList)) throw new ServiceException("该试卷没有试题,请重新选择");
			//3.保存到试卷发布详情表，用于学员考试
			paperDetailList.forEach(paperDetailEntity -> {
				PaperReleaseDetailEntity releaseDetailEntity = new PaperReleaseDetailEntity();
				BeanUtil.copyProperties(paperDetailEntity, releaseDetailEntity, "id");

				releaseDetailEntity.setReleaseId(vo.getId());
				//设置每道题的分数
				setQuestionScore(releaseDetailEntity.getQuestionType(), vo, releaseDetailEntity);
				releaseDetailEntity.setQuestionId(paperDetailEntity.getQuestionBankId());
				paperReleaseDetailService.save(releaseDetailEntity);
			});
		}


		if (1==vo.getIsRule()){
			List<AutoExtractParamBO> ruleList = vo.getRuleList();
			if (CollectionUtil.isEmpty(ruleList)) throw new TrainingServiceException("至少新增一条组卷规则");
			for (AutoExtractParamBO bo:ruleList){
				if (QuestionType.SHORT.getCode().intValue()==bo.getQuestionType()){
					vo.setIsNeedReview(1);
					break;
				}
			}


			if (null==vo.getPeriod() || vo.getPeriod()<0 ) vo.setPeriod(0);
			if (null==vo.getIntegral() || vo.getIntegral()<0) vo.setIntegral((float)0);
			paperReleaseService.save(vo);//保存试卷发布
			//试卷规则处理
			List<PaperReleaseRuleEntity> ruleEntityList = ruleList.stream().map(rule -> {
				PaperReleaseRuleEntity releaseRuleEntity = new PaperReleaseRuleEntity();
				BeanUtil.copy(rule, releaseRuleEntity);
				releaseRuleEntity.setReleaseId(vo.getId());
				return releaseRuleEntity;
			}).collect(Collectors.toList());
			paperReleaseRuleService.saveBatch(ruleEntityList);
		}

		return R.success("发布成功");
	}

	/**
	 * 获取考试试卷
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/get-exam-paer")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "获取考试试卷", notes = "传入releaseId")
	public R examPaper(Long releaseId) {
//		PaperReleaseVO examPaper = paperReleaseService.getExamPaper(releaseId);
//		if (null != examPaper)
//			examPaper.setPaperReleaseDetailList(paperService.sortExamPaperDetailByQuestionType(examPaper.getPaperReleaseDetailList()));

		PaperReleaseEntity paperReleaseEntity=paperReleaseService.getById(releaseId);
		PaperReleaseVO examPaper = paperReleaseService.getExamPaper(releaseId);

		if (null==paperReleaseEntity.getIsRule()||0==paperReleaseEntity.getIsRule()){//非规则组卷的试题
			examPaper.setPaperReleaseDetailList(paperService.sortExamPaperDetailByQuestionType(examPaper.getPaperReleaseDetailList()));
		}else {//规则组卷的试题
			examPaper=paperReleaseService.getRuleExamPaper(releaseId);
		}

		return R.data(examPaper);
	}


	/**
	 * 批阅试卷步骤
	 * 1.获取所有需要批阅的考试
	 * 2.获取指定考试的所有未批阅的试卷
	 * 3.查看某试卷需要批阅的试题
	 * 4.批阅试题
	 */
	/**
	 * 1.获取所有需要批阅的试卷
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/get-need-review-release")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "获取所有需要批阅的考试", notes = "传入paperRelease")
	public R getNeedReviewRelease(PaperReleaseEntity paperRelease, Query query) {
		LambdaQueryWrapper<PaperReleaseEntity> lambdaQueryWrapper=new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(PaperReleaseEntity::getIsNeedReview, 1);
		if (StringUtils.isNotBlank(paperRelease.getReleaseName())){
			lambdaQueryWrapper.like(PaperReleaseEntity::getReleaseName, paperRelease.getReleaseName());
		}
		lambdaQueryWrapper.orderByDesc(PaperReleaseEntity::getCreateTime);

		IPage<PaperReleaseEntity> pages = paperReleaseService.page(Condition.getPage(query), lambdaQueryWrapper);
		return R.data(PaperReleaseWrapper.build().pageVO(pages));
	}

	/**
	 * 2.获取指定考试的学生作答试卷
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/get-answer-paper")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "获取待批阅的试卷", notes = "传入answerEntity")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public R getAnsewerPaper(PaperAnswerVO vo, Query query) {
		vo.setStatus(1);//已交卷
		vo.setIsReview(0);//未批阅的
		IPage<PaperAnswerVO> pages = answerService.selectAnswerPage(Condition.getPage(query), vo);
		return R.data(pages);
	}

	/**
	 * 3.查看某试卷需要批阅的试题
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/get-review-answer-option")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "获取试卷需要批阅的试题", notes = "传入answerEntity")
	public R getReviewAnswerOption(PaperAnswerVO answer) {
		return R.data(answerService.selectReviewAnswerPage(answer));
	}

	/**
	 * 4.批阅试题
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/review-answer")
	@ApiOperationSupport(order = 13)
	@ApiOperation(value = "批阅试卷", notes = "传入AnswerOptionEntity")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	@ServiceLog(value = TrainingOperateConstant.RELEASE,operate = TrainingOperateConstant.ADD,describe = "试卷批阅")
	public R reviewAnswer(@RequestBody @Valid List<PaperAnswerVO> list) {
		int addScore = 0;
		Long answerId = list.get(0).getId();
		for (PaperAnswerVO paperAnswerVO : list) {
			if (paperAnswerVO.getQuestionScore() > paperAnswerVO.getValue())
				throw new TrainingServiceException("得分不可大于该试题分数!");
			if (paperAnswerVO.getQuestionScore() < 0) throw new TrainingServiceException("分数不可为负值!");
			addScore += paperAnswerVO.getQuestionScore();
		}
		PaperAnswerEntity paperAnswerEntity = answerService.getById(answerId);
		if (null != paperAnswerEntity) {
			paperAnswerEntity.setScore(paperAnswerEntity.getScore() + addScore); //成绩加分
			paperAnswerEntity.setReviewUser(AuthUtil.getUserId());
			paperAnswerEntity.setIsReview(1);//设置为已批阅
			answerService.updateById(paperAnswerEntity);

			PaperReleaseEntity paperReleaseEntity = paperReleaseService.getById(paperAnswerEntity.getPaperReleaseId());
			if (paperAnswerEntity.getScore() >= paperReleaseEntity.getPassingScore()) { //如果合格，发放该课程的学时和积分
				IntegralLogVO vo = integralLogService.generalIntegralByExam(paperReleaseEntity);
				vo.setUserId(paperAnswerEntity.getUserId());
				integralLogService.addIntegral(vo);
			}
		}





		
		return R.success("批阅成功");
	}


	/**
	 * 考试下拉列表
	 */
	@GetMapping("/select")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "考试下拉列表", notes = "")
	public R select(@ApiIgnore @RequestParam Map<String, Object>  entity) {
			QueryWrapper<PaperReleaseEntity> queryWrapper = Condition.getQueryWrapper(entity, PaperReleaseEntity.class);
			return R.data(paperReleaseService.list(queryWrapper));
	}



}
